package com.topisv.tms.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.topisv.tms.entity.Customers;
import com.topisv.tms.entity.EdiGoodsSku;
import com.topisv.tms.entity.EdiOrderItem;
import com.topisv.tms.entity.QueryParamHolder;
import com.topisv.tms.entity.stock.ViewCusStock;
import com.topisv.tms.exception.ErrorCode;
import com.topisv.tms.exception.PaiUException;
import com.topisv.tms.repository.CustomersDao;
import com.topisv.tms.repository.EdiGoodsSkuDao;
import com.topisv.tms.rest.qimen.qmentity.request.deliveryorder.DeliveryOrderItem;
import com.topisv.tms.rest.qimen.qmentity.request.deliveryorder.DeliveryOrderRequest;
import com.topisv.tms.rest.qimen.qmentity.request.stockout.StockOutItem;
import com.topisv.tms.rest.qimen.qmentity.request.stockout.StockOutRequest;
import com.topisv.tms.service.base.BaseService;

//Spring Bean的标识.
@Component
// 默认将类中的所有public函数纳入事务管理.
@Transactional(readOnly = true)
public class EdiGoodsSkuService extends BaseService{
	private static final Logger log = LoggerFactory.getLogger(EdiGoodsSkuService.class);
	
	@Autowired
	private EdiGoodsSkuDao ediGoodsSkuDao;
	@Autowired
	private CustomersDao customersDao;
	
	
	public void setViewStocks(String customerCode,List<ViewCusStock> viewStocks){
		if(viewStocks!=null){
			for(ViewCusStock v:viewStocks){
				try {
					EdiGoodsSku ediGoodsSku=ediGoodsSkuDao.findByCustomerCodeAndSku(customerCode, v.getSku());
                    if(ediGoodsSku!=null){
                    	v.setEdiGoodsSku(ediGoodsSku);
                    }
				} catch (Exception e) {
					
				}
			}

		}
	}
	
	@Transactional(rollbackFor=Exception.class,readOnly = false)
	public EdiGoodsSku save(EdiGoodsSku arg0){
		return ediGoodsSkuDao.save(arg0);
	}
	
	public EdiGoodsSku findByCustomerCodeAndSku(String customerCode,String sku){
		return ediGoodsSkuDao.findByCustomerCodeAndSku(customerCode, sku);
	}
	
	public EdiGoodsSku findByCustomerCodeAndBar(String customerCode,String bar) {
		return ediGoodsSkuDao.findByCustomerCodeAndBar(customerCode, bar);
	}
	
	public EdiGoodsSku findBySku(String sku){
		return ediGoodsSkuDao.findBySku(sku);
	}
	public EdiGoodsSku findBySkuAndCustomerCode(String sku,String customerCode){
		return ediGoodsSkuDao.findBySkuAndCustomerCode(sku, customerCode) ;
	}
	
	@Transactional(rollbackFor=Exception.class,readOnly = false)
	public Map<String, List<EdiGoodsSku>> save(String customerCode,List<EdiGoodsSku> ediGoodsSkus,boolean overwrite) throws Exception{
		Map<String, List<EdiGoodsSku>> maps=new HashMap<String, List<EdiGoodsSku>>();
		List<EdiGoodsSku> normalSkus=new ArrayList<EdiGoodsSku>();
		List<EdiGoodsSku> exceptionSkus=new ArrayList<EdiGoodsSku>();
		maps.put("normal", normalSkus);
		maps.put("exception", exceptionSkus);
	
		for (int i = 0; i < ediGoodsSkus.size(); i++) {
			EdiGoodsSku ediGoodsSku = ediGoodsSkus.get(i);
			ediGoodsSku.setCustomerCode(customerCode);
			String sku=ediGoodsSku.getSku();
			if (null == sku || "".equals(sku.trim())) {
				exceptionSkus.add(ediGoodsSku);
			} else {
				try {
					EdiGoodsSku oldGoodSku =ediGoodsSkuDao.findByCustomerCodeAndSku(customerCode, sku);
					if(oldGoodSku != null){
						if(overwrite){
							BeanUtils.copyProperties(ediGoodsSku,oldGoodSku,new String[]{"id"});
							ediGoodsSku = oldGoodSku;
						} else {
							exceptionSkus.add(ediGoodsSku);
							continue;
						}
					}
					normalSkus.add(ediGoodsSku);
					ediGoodsSkuDao.save(ediGoodsSku);
				} catch (Exception e) {
					log.error("save GoodSku Exception:"+ediGoodsSku.getCustomerCode()+":"+ediGoodsSku.getSku()+"-"+ediGoodsSku.getSkuName(),e);
					exceptionSkus.add(ediGoodsSku);
				}
			}
		} // end for

    	return maps;
	}
	
	@Transactional(rollbackFor=Exception.class,readOnly = false)
	public void update(EdiGoodsSku ediGoodsSku){
		ediGoodsSkuDao.deleteByCustomerCodeAndSku(ediGoodsSku.getCustomerCode(), ediGoodsSku.getSku());
		ediGoodsSkuDao.save(ediGoodsSku);
	}
	
	@Transactional(rollbackFor=Exception.class,readOnly = false)
	public void delete(EdiGoodsSku ediGoodsSku){
		ediGoodsSkuDao.deleteByCustomerCodeAndSku(ediGoodsSku.getCustomerCode(), ediGoodsSku.getSku());
	}
	
	@Transactional(rollbackFor=Exception.class,readOnly = false)
	public void saveException(List<EdiGoodsSku> ediGoodsSkus) throws Exception{
		if (ediGoodsSkus != null) {
			for (int i = 0; i < ediGoodsSkus.size(); i++) {
				EdiGoodsSku ediGoodsSku = ediGoodsSkus.get(i);
				String des = ediGoodsSku.getDes();
				if (des != null) {
					String[] dess = des.split(" ");
					if(dess.length==2){
						ediGoodsSku.setCol(dess[0]);
						ediGoodsSku.setSiz(dess[1]);
					}else if(dess.length==1){
						ediGoodsSku.setCol(dess[0]);
					}
				}
			}
			ediGoodsSkuDao.save(ediGoodsSkus);
		}
	}
	

	
	public List<EdiGoodsSku> findAll() {
		return (List<EdiGoodsSku>) ediGoodsSkuDao.findAll();
	}
	
	@Transactional(rollbackFor=Exception.class,readOnly = false)
	public void save(List<EdiGoodsSku> ediGoodsSkus,
			EdiOrderItemService ediOrderItemService) {
		if(ediGoodsSkus==null){
			return;
		}
		List<EdiOrderItem> ediOrderItems = ediOrderItemService.findAll();
		List<EdiGoodsSku> temps = new ArrayList<EdiGoodsSku>();
		for (int j = 0; j < ediOrderItems.size(); j++) {
			EdiOrderItem ediOrderItem = ediOrderItems.get(j);
			EdiGoodsSku ediGoodsSku = new EdiGoodsSku();
			ediGoodsSku.setSku(ediOrderItem.getSku());
			ediGoodsSku.setTbSkuid(ediOrderItem.getTdSkuId());
			for (int i = 0; i < ediGoodsSkus.size(); i++) {
				EdiGoodsSku temp = ediGoodsSkus.get(i);
				ediGoodsSku.setBar(temp.getBar());
				ediGoodsSku.setDes(temp.getDes());
				ediGoodsSku.setGwt(temp.getGwt());
				ediGoodsSku.setHei(temp.getHei());
				ediGoodsSku.setLen(temp.getLen());
				ediGoodsSku.setMem(temp.getMem());
				ediGoodsSku.setNwt(temp.getNwt());
				ediGoodsSku.setUnt(temp.getUnt());
				ediGoodsSku.setVol(temp.getVol());
				ediGoodsSku.setWid(temp.getWid());

				String des = temp.getDes();
				if (des != null) {
					String[] dess = des.split(" ");
					ediGoodsSku.setCol(dess[0]);
					ediGoodsSku.setSiz(dess[1]);
				}

			}
			temps.add(ediGoodsSku);
		}
		ediGoodsSkuDao.save(temps);

	}

	/**
	 * 分页查询商品信息
	 * @param param
	 * @param pageNumber
	 * @param pageSize
	 * @return
	 */
	public Page<EdiGoodsSku> loadGoods(Map<String, Object> param,int pageNumber, int pageSize) {
		Sort sort = new Sort(Sort.Direction.DESC,"id");
	    PageRequest pageRequest = new PageRequest(pageNumber-1, pageSize, sort);
	    Specification<EdiGoodsSku> spec =this.getWhereClause(param);
	    Page<EdiGoodsSku> page = this.ediGoodsSkuDao.findAll(spec, pageRequest);
	    if(page!=null){
	    	List<EdiGoodsSku> list=page.getContent();
	    	for (EdiGoodsSku goods : list) {
				this.setDetail(goods);
			}
	    }
	    return page;
	}
	
	/**
	 * 分页查询商品信息
	 * @param paramHolder
	 * @return Page<EdiGoodsSku>
	 * @throws Exception 
	 */
	public Page<EdiGoodsSku> loadGoods(QueryParamHolder paramHolder) throws Exception {
		Page<EdiGoodsSku> page = findByJson(paramHolder, ediGoodsSkuDao, EdiGoodsSku.class);
		if (page != null) {
			List<EdiGoodsSku> list = page.getContent();
			for (EdiGoodsSku goods : list) {
				this.setDetail(goods);
			}
		}
		return page;
	}
	/**
	 * 查询商品信息
	 * @param paramHolder
	 * @return Page<EdiGoodsSku>
	 * @throws Exception 
	 */
	public EdiGoodsSku loadById(Long id) {
		return ediGoodsSkuDao.findOne(id);
	}
	
	/**
	 * 查询商品信息
	 * @param param
	 * @param pageNumber
	 * @param pageSize
	 * @return
	 */
	public List<EdiGoodsSku> loadGoods(Map<String, Object> param) {
		Sort sort = new Sort(Sort.Direction.DESC,"id");
	    Specification<EdiGoodsSku> spec =this.getWhereClause(param);
	    List<EdiGoodsSku> list = this.ediGoodsSkuDao.findAll(spec,sort);
    	for (EdiGoodsSku goods : list) {
			this.setDetail(goods);
		}
	    return list;
	}
	
	
	/**
	 * 条件封装
	 * @param param
	 * @return
	 */
	private Specification<EdiGoodsSku> getWhereClause(final Map<String, Object> param) {
		 return new Specification<EdiGoodsSku>(){
		    @Override
		    public Predicate toPredicate(Root<EdiGoodsSku> r, CriteriaQuery<?> q, CriteriaBuilder cb) {
		      Predicate pre = cb.conjunction();
		      
		      //customerCode
		      String customerCode=(String) param.get("customerCode");
		      if(StringUtils.isNotBlank(customerCode)){
					pre.getExpressions().add(cb.like(r.<String>get("customerCode"), customerCode));
			  }
		      
		      //skuName
		      String skuName=(String) param.get("skuName");
		      if(StringUtils.isNotBlank(skuName)){
		         pre.getExpressions().add(cb.like(r.<String>get("skuName"),"%"+skuName+"%"));
			  }
		      
		      //sku
		      String sku=(String) param.get("sku");
		      if(StringUtils.isNotBlank(sku)){
		         pre.getExpressions().add(cb.like(r.<String>get("sku"),"%"+sku+"%"));
			  }
		      
		      //bar
		      String bar=(String) param.get("bar");
		      if(StringUtils.isNotBlank(bar)){
		         pre.getExpressions().add(cb.like(r.<String>get("bar"),"%"+bar+"%"));
			  }
		      return pre;
		    }
		  };
	}
	
	/**
	 * 设置属性
	 * @param task
	 */
	private void setDetail(EdiGoodsSku goods){
		//customer
		String customerCode=goods.getCustomerCode();
		Customers customer=this.customersDao.findByCustomerCode(customerCode);
		goods.setCustomer(customer);
	}

	/**
	 * 修改商品重量
	 * @param goodsId
	 * @param weight
	 */
	@Transactional(readOnly = false)
	public void updateWeight(Long goodsId, Integer weight) {
		EdiGoodsSku goods=this.ediGoodsSkuDao.findOne(goodsId);
		if(goods!=null){
			goods.setWeight(weight);
			this.ediGoodsSkuDao.save(goods);
		}
	}
	
	/**
	 * 修改包装重量
	 * @param goodsId
	 * @param weight
	 */
	@Transactional(readOnly = false)
	public void updateWeightPkg(Long goodsId, Integer weight) {
		EdiGoodsSku goods=this.ediGoodsSkuDao.findOne(goodsId);
		if(goods!=null){
			goods.setWeightPkg(weight);
			this.ediGoodsSkuDao.save(goods);
		}
	}
	/**
	 * 修改SKU名称
	 * @param goodsId
	 * @param name
	 */
	@Transactional(readOnly = false)
	public void updateSkuName(Long goodsId, String skuName) {
		EdiGoodsSku goods=this.ediGoodsSkuDao.findOne(goodsId);
		if(goods!=null){
			goods.setSkuName(skuName);
			this.ediGoodsSkuDao.save(goods);
		}
	}
	
	/**
	 * 出库单报文商品itemid校验
	 * @param items
	 * @return
	 */
	public Map checkItemId(StockOutRequest stockOutRequest){
		Map<String,String> map = new HashMap<String,String>() ;
		List<StockOutItem> items = stockOutRequest.getStockOutItems();
		StringBuffer sb = new StringBuffer("");
		String customerCode = "" ;
		String itemId = "" ;
		String msg = "success" ;
		for(StockOutItem stockOutItem:items){
			customerCode = stockOutItem.getOwnerCode() ;
			itemId = stockOutItem.getItemId() ;
			EdiGoodsSku ediGoodsSku = ediGoodsSkuDao.findOne(Long.parseLong(itemId)) ;
			if(null == ediGoodsSku||!ediGoodsSku.getCustomerCode().equals(customerCode)){
				sb.append("商品编码[").append(itemId).append("]不存在;") ;
				msg = "failure";
			}
		}
		map.put("msg", msg) ;
		if(msg.equals("failure")){
			map.put("message", sb.toString()) ;
		}
		return map; 
	}
	/**
	 * 出库单报文商品itemid校验是否为空
	 * @param stockOutRequest
	 * @return
	 */
	public Map<String,String> toCheckItemId(DeliveryOrderRequest deliveryOrderRequest){
		Map<String,String> map = new HashMap<String,String>() ;
		List<DeliveryOrderItem> items = deliveryOrderRequest.getDeliveryOrderItems();
		StringBuffer sb = new StringBuffer("");
		String msg = "success" ;
		for(DeliveryOrderItem item:items){
			if(StringUtils.isBlank(item.getItemId())){
				sb.append("仓储系统商品编码必填！") ;
				msg = "failure";
				break ;
			}
			EdiGoodsSku goodsSku = ediGoodsSkuDao.findOne(Long.parseLong(item.getItemId()));
            if (goodsSku == null) {
                sb.append("仓储系统商品编码有误！") ;
                msg = "failure";
                break ;
            }
		}
		map.put("msg", msg) ;
		if(StringUtils.equals(msg, "failure")){
			map.put("message", sb.toString());
		}
		return map; 
	}
	
}
